package com.wswy.wzcx.api;

import android.os.Build;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.text.TextUtils;
import android.util.Pair;

import com.blankj.utilcode.util.SPUtils;
import com.che.libcommon.api.ApiException;
import com.che.libcommon.api.BaseApiClient;
import com.che.libcommon.api.BaseResult;
import com.che.libcommon.api.page.PageList;
import com.che.libcommon.utils.JsonKit;
import com.che.libcommon.utils.RxHelper;
import com.che.libcommon.utils.optional.Optional;
import com.google.gson.reflect.TypeToken;
import com.wswy.wzcx.AppContext;
import com.wswy.wzcx.BuildConfig;
import com.wswy.wzcx.aanewApi.baseApi.Interceptor.LoggingInterceptor;
import com.wswy.wzcx.api.Gov122.GovResult;
import com.wswy.wzcx.api.ListResult.ListData;
import com.wswy.wzcx.model.AdConfigs;
import com.wswy.wzcx.model.BookMode;
import com.wswy.wzcx.model.DataCenter;
import com.wswy.wzcx.model.DeviceMod;
import com.wswy.wzcx.model.JZCFMode;
import com.wswy.wzcx.model.MessageDetail;
import com.wswy.wzcx.model.MessageMode;
import com.wswy.wzcx.model.MyOrderMode;
import com.wswy.wzcx.model.OCRItem;
import com.wswy.wzcx.model.OCRResult;
import com.wswy.wzcx.model.PaymentOrder;
import com.wswy.wzcx.model.TabConfResp;
import com.wswy.wzcx.model.TrafficViolationInfo;
import com.wswy.wzcx.model.UpgradeModel;
import com.wswy.wzcx.model.UserMode;
import com.wswy.wzcx.model.WZCity;
import com.wswy.wzcx.model.car.CarExtendInfo;
import com.wswy.wzcx.model.car.CarTypeResp;
import com.wswy.wzcx.model.car.JZGCity;
import com.wswy.wzcx.model.conf.SysConfMap;
import com.wswy.wzcx.model.core.BgWorkModel;
import com.wswy.wzcx.model.core.OSSToken;
import com.wswy.wzcx.model.core.OSSUploadResult;
import com.wswy.wzcx.model.coupon.CouponResp;
import com.wswy.wzcx.model.dmv.DepartmentInfo;
import com.wswy.wzcx.model.dmv.ServiceCatagory;
import com.wswy.wzcx.model.fkdj.FineExtraFeeResp;
import com.wswy.wzcx.model.fkdj.FinePaymentDetail;
import com.wswy.wzcx.model.gov.GovParseResp;
import com.wswy.wzcx.model.license.CheckLicenseAvailableModel;
import com.wswy.wzcx.model.license.UserCarInfo;
import com.wswy.wzcx.model.news.NewsCategory;
import com.wswy.wzcx.model.news.NewsModel;
import com.wswy.wzcx.model.njdb.NjdbPreModel;
import com.wswy.wzcx.model.pay.OrderStatus;
import com.wswy.wzcx.model.resp.CaptchaData;
import com.wswy.wzcx.model.resp.CaptchaValidData;
import com.wswy.wzcx.model.resp.CityListResp;
import com.wswy.wzcx.model.resp.OilPriceResp;
import com.wswy.wzcx.model.resp.PhoneCheckResp;
import com.wswy.wzcx.model.resp.PhoneSmsCodeValidResp;
import com.wswy.wzcx.model.resp.TrafficViolationResp;
import com.wswy.wzcx.model.topic.CommentModel;
import com.wswy.wzcx.model.topic.TopicListResp;
import com.wswy.wzcx.model.topic.TopicModel;
import com.wswy.wzcx.model.topic.TopicTagType;
import com.wswy.wzcx.model.topic.TopicViewResp;
import com.wswy.wzcx.model.weather.CarTips;
import com.wswy.wzcx.model.wzdb.WzdbCreateResp;
import com.wswy.wzcx.model.wzdb.WzdbOrderInfo;
import com.wswy.wzcx.module.ChannelManager;
import com.wswy.wzcx.module.DebugConfig;
import com.wswy.wzcx.module.GlobalConfigManager;
import com.wswy.wzcx.module.LocManager;
import com.wswy.wzcx.module.validator.IValidator;
import com.wswy.wzcx.module.validator.ValidReq;
import com.wswy.wzcx.module.validator.ValidatorResult;
import com.wswy.wzcx.statistics.StatTools;
import com.wswy.wzcx.statistics.StatisticsId;
import com.wswy.wzcx.ui.data.JZCFResult;
import com.wswy.wzcx.ui.data.WZDBMode;
import com.wswy.wzcx.ui.module.feedback.CommonFeedbackQA;
import com.wswy.wzcx.ui.module.feedback.FeedbackModel;
import com.wswy.wzcx.utils.FileUtils;
import com.wswy.wzcx.utils.Tools;

import io.reactivex.Flowable;
import io.reactivex.Single;
import io.reactivex.SingleSource;
import io.reactivex.functions.Consumer;
import io.reactivex.functions.Function;
import io.reactivex.functions.Predicate;

import java.io.File;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.TreeMap;
import java.util.UUID;
import java.util.concurrent.Callable;
import java.util.concurrent.TimeUnit;

import okhttp3.ConnectionSpec;
import okhttp3.FormBody;
import okhttp3.MediaType;
import okhttp3.MultipartBody;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.RequestBody;
import okhttp3.Response;

import org.json.JSONObject;

import javax.net.ssl.SSLContext;

import okhttp3.TlsVersion;
import retrofit2.Retrofit.Builder;

public final class Api extends BaseApiClient {

    private static final String USER_CAR_ID = "userCarId";

    private static class InstanceHolder {
        private static final Api INSTANCE = new Api();
    }

    public static Api get() {
        return InstanceHolder.INSTANCE;
    }

    private BaseService baseService;


    private OkHttpClient okHttpClient;

    private Api() {
        baseService = createRetrofit().create(BaseService.class);
        init();
    }


    private void init() {
        int initVer = SPUtils.getInstance().getInt("api_init_last_ver", 0);
        if (initVer < 71) {
            //removeCache("api_car_brands");
            removeCache("api_car_type_city"); //更新城市缓存
        }
        SPUtils.getInstance().put("api_init_last_ver", BuildConfig.VERSION_CODE);

    }


    @Override
    protected String getBaseUrl() {
        String apiServer = Configs.API_SERVER;
        DebugConfig debugConfig = GlobalConfigManager.getInstance().getDebugConfig();
        if (debugConfig.forceHttp && apiServer.startsWith("https://")) {
            return apiServer.replaceFirst("https://", "http://");
        } else {
            return apiServer;
        }

    }

    @Override
    protected Builder createRetrofitBuilder(OkHttpClient client) {
        Builder retrofitBuilder = super.createRetrofitBuilder(client);
        okHttpClient = client;
        return retrofitBuilder;
    }


    @Override
    protected OkHttpClient.Builder createHttpClientBuilder() {
//        OkHttpClient.Builder httpClientBuilder = super.createHttpClientBuilder();
//        httpClientBuilder.followRedirects(true);
//        httpClientBuilder.followSslRedirects(true);
//        httpClientBuilder.retryOnConnectionFailure(true);
//        httpClientBuilder.cache(null);
//        httpClientBuilder.readTimeout(2, TimeUnit.MINUTES);
//        httpClientBuilder.writeTimeout(1, TimeUnit.MINUTES);
//        httpClientBuilder.connectTimeout(1, TimeUnit.MINUTES);
//        httpClientBuilder.addInterceptor(new ParamInterceptor());
////        return httpClientBuilder;
//        return enableTls12OnPreLollipop(httpClientBuilder);
        OkHttpClient.Builder httpClientBuilder = super.createHttpClientBuilder();
        httpClientBuilder.readTimeout(2, TimeUnit.MINUTES);
        httpClientBuilder.writeTimeout(1, TimeUnit.MINUTES);
        httpClientBuilder.connectTimeout(1, TimeUnit.MINUTES);
        httpClientBuilder.addInterceptor(new ParamInterceptor());
        httpClientBuilder .addInterceptor(new LoggingInterceptor());
        return httpClientBuilder;
    }

    public OkHttpClient.Builder enableTls12OnPreLollipop(OkHttpClient.Builder client) {
        if (Build.VERSION.SDK_INT >= 16 && Build.VERSION.SDK_INT < 22) {
            try {
                SSLContext sc = SSLContext.getInstance("TLSv1.2");
                sc.init(null, null, null);
                client.sslSocketFactory(new Tls12SocketFactory(sc.getSocketFactory()));
                ConnectionSpec cs = new ConnectionSpec.Builder(ConnectionSpec.MODERN_TLS)
                        .tlsVersions(TlsVersion.TLS_1_2)
                        .build();
                List<ConnectionSpec> specs = new ArrayList<>();
                specs.add(cs);
                specs.add(ConnectionSpec.COMPATIBLE_TLS);
                specs.add(ConnectionSpec.CLEARTEXT);
                client.connectionSpecs(specs);
            } catch (Exception exc) {
//                Log.e("OkHttpTLSCompat", "Error while setting TLS 1.2", exc);
            }
        }
        return client;
    }


    OkHttpClient getOkHttpClient() {
        return okHttpClient;
    }

    private class ListMapFunction<T> implements Function<Optional<ListData<T>>, Optional<List<T>>> {

        @Override
        public Optional<List<T>> apply(Optional<ListData<T>> listDataOptional) throws Exception {
            ListData<T> tListData = listDataOptional.orNull();
            if (tListData != null) {
                return Optional.ofNullable(tListData.list);
            }
            return Optional.absent();
        }
    }

    @Override
    protected <T> Single<Optional<T>> wrapToSingle(Flowable<? extends BaseResult<T>> flowable, boolean switch2Main) {
        return super.wrapToSingle(flowable, switch2Main).doOnError(new Consumer<Throwable>() {
            @Override
            public void accept(Throwable throwable) throws Exception {
                if (throwable instanceof ApiException) {
                    int code = ((ApiException) throwable).code;
                    if (ErrorCode.isTokenInvalid(code)) {
                        DataCenter.get().cleanUser();
                    }
                }
            }
        });
    }

    public Single<Optional<DeviceMod>> requestDevice(final Map<String, String> map) {

        return wrapToSingle(baseService.requestDevice(ReqParameter.generate().addAll(map).getParams()));
    }


    private Single<Optional<JZCFResult>> wrapJzcf(Single<Optional<JZCFResult>> apiQuery, final String jszh, final String dabh) {
        Single<Optional<JZCFResult>> gwQuery = Single
                .fromCallable(new Callable<Optional<JZCFResult>>() {
                    @Override
                    public Optional<JZCFResult> call() throws Exception {

                        try {
                            GovResult govResult = Gov122.get122ScoreData(jszh, dabh);
                            if (govResult != null) {
                                Map<String, String> commonParams = govResult.getCommonParams();
                                if (commonParams != null) {
                                    Optional<GovParseResp> govParseRespOptional = govQueryParse(commonParams)
                                            .blockingGet();
                                }
                            }
                        } catch (Throwable e) {
                            e.printStackTrace();
                        }
                        return Optional.absent();
                    }
                }).timeout(20, TimeUnit.SECONDS, Single.just(Optional.<JZCFResult>absent())).compose(RxHelper.<Optional<JZCFResult>>io2main());

        return Single.concat(gwQuery, apiQuery).filter(new Predicate<Optional<JZCFResult>>() {
            @Override
            public boolean test(Optional<JZCFResult> jzcfModeOptional) throws Exception {
                return jzcfModeOptional.isPresent();
            }
        }).lastOrError();
    }

    /**
     * 驾驶证列表
     *
     * @return
     */
    public Single<Optional<List<JZCFMode>>> fetchJZList() {
        Map<String, String> params = ReqParameter.generate().getParams();
        return wrapToSingle(baseService.fetchJZList(params));
    }

    /**
     * 保存或修改驾驶证
     *
     * @param mode 如果驾驶证id为空，添加驾驶证
     * @return
     */
    public Single<Optional<JZCFMode>> submitJZCFMode(final JZCFMode mode) {
        ReqParameter parameter = ReqParameter.generate().add("file_number", mode.getFileNumber())
                .add("initial_license_date", mode.getInitDate())
                .add("number", mode.getNumber())
                .add("real_name", mode.getNikeName());
        if (!TextUtils.isEmpty(mode.get_id())) {
            parameter.add("id", mode.get_id());
            return wrapToSingle(baseService.submitEditJZCFMode(parameter.getParams()));
        }
        Map<String, String> params = parameter.getParams();
        return wrapToSingle(baseService.submitJZCFMode(params));
    }

    /**
     * 删除驾驶证
     *
     * @param id 驾驶证id
     * @return
     */
    public Single<Optional<String>> deleteJZCFMode(String id) {
        Map<String, String> id1 = ReqParameter.generate().add("id", id).getParams();
        return wrapToSingle(baseService.deleteJZCFMode(id1));
    }

    /**
     * 驾驶证查分
     *
     * @param _id           驾驶证id
     * @param licenseId     驾驶证号
     * @param licenseNumber 档案编号
     * @return
     */
    public Single<Optional<JZCFResult>> fetchJZCFResult(String _id, String licenseId, String licenseNumber) {
        Map<String, String> params = ReqParameter.generate()
                .add("id", _id)
                .add("licenseId", licenseId)
                .add("licenseNumber", licenseNumber)
                .getParams();
        return wrapJzcf(wrapToSingle(baseService.fetchJZCFResult(params)), licenseNumber, licenseId);
    }


    /**
     * 罚款代缴-根据罚单编号检测提示信息
     *
     * @param fineNumber
     * @return
     */
    public Single<Optional<String>> fineAreaHint(String fineNumber) {
        return wrapToSingle(baseService.areaFineHint(ReqParameter.generate().add("fineNumber", fineNumber).getParams()));
    }

    /**
     * 罚款代缴-计算服务费
     *
     * @param amount 罚单金额
     * @param date   罚单时间
     * @return
     */
    public Single<Optional<FineExtraFeeResp>> getFKDJExtraFee(String amount, String date) {
        return wrapToSingle(baseService.getFKDJExtraFee(ReqParameter.generate()
                .add("pinZhenHao", "")
                .add("money", amount)
                .add("date", date)
                .getParams()));
    }


    /**
     * 发送短信验证码
     *
     * @param type   验证码类型
     * @param text   手机号
     * @param ticket 腾讯验证码
     * @return
     */
    public Single<Optional<Boolean>> fetchPhoneVer(int type, String text, ValidatorResult ticket) {
        ReqParameter parameter = ReqParameter.generate();
        parameter.add("codeType", type)
                .add("ticket", ticket.getTicket())
                .add("mobile", text).getParams();
        return wrapToSingle(baseService.fetchPhoneVer(parameter.getParams()));
    }

    /**
     * 用户账号密码登录
     *
     * @param acc 手机号
     * @param pwd 密码
     * @return
     */
    public Single<Optional<UserMode>> fetchLoginAcc(String acc, String pwd) {
        Map<String, String> map = ReqParameter.generate()
                .add("pass", pwd)
                .add("mobile", acc).getParams();
        return wrapToSingle(baseService.fetchAccLogin(map));
    }

    /**
     * 用户短信登录
     *
     * @param text    手机号
     * @param verCode 短信验证码
     * @return
     */
    public Single<Optional<UserMode>> fetchLoginPhone(String text, String verCode) {
        Map<String, String> map = ReqParameter.generate()
                .add("code", verCode)
                .add("mobile", text)
                .getParams();
        return wrapToSingle(baseService.fetchLoginPhone(map));
    }

    /**
     * 运营商一键登录
     *
     * @param token 一键登录token
     * @return
     */
    public Single<Optional<UserMode>> fetchOneKeyLogin(String token) {
        Map<String, String> map = ReqParameter.generate()
                .add("flashToken", token)
                .add("syAppId", BuildConfig.SHANYAN_APPID)
                .getParams();
        return wrapToSingle(baseService.fetchOneKeyLogin(map));
    }

    /**
     * 手机号检测
     *
     * @param phone
     * @return
     */
    public Single<Optional<PhoneCheckResp>> phoneCheck(String phone) {
        Map<String, String> map = ReqParameter.generate()
                .add("mobile", phone)
                .getParams();
        return wrapToSingle(baseService.phoneCheck(map));
    }

    /**
     * 微信绑定检测
     *
     * @param phone
     * @param wechatCode
     * @return
     */
    public Single<Optional<PhoneCheckResp>> wechatBindCheck(String phone, String wechatCode) {
        Map<String, String> map = ReqParameter.generate()
                .add("mobile", phone)
                .add("wechatCode", wechatCode)
                .getParams();
        return wrapToSingle(baseService.wechatBindCheck(map));
    }

    /**
     * 短信验证码验证
     *
     * @param phone   手机号
     * @param smsCode 短信验证码
     * @return
     */
    public Single<Optional<PhoneSmsCodeValidResp>> phoneSmsCodeValid(String phone, String smsCode) {
        Map<String, String> map = ReqParameter.generate()
                .add("mobile", phone)
                .add("code", smsCode)
                .getParams();
        return wrapToSingle(baseService.phoneSmsCodeValid(map));
    }

    /**
     * 用户注册
     *
     * @param phone   手机号
     * @param verCode 短信验证成功code
     * @param pass    密码
     * @return
     */
    public Single<Optional<UserMode>> regLogin(String phone, String verCode, String pass) {
        Map<String, String> map = ReqParameter.generate()
                .add("verifyIdentity", verCode)
                .add("mobile", phone)
                .add("pass", pass)
                .getParams();
        return wrapToSingle(baseService.regLogin(map));
    }

    /**
     * 用户-微信登录
     *
     * @param wechatCode 微信sdk返回的code
     * @return
     */
    public Single<Optional<UserMode>> wechatLogin(String wechatCode) {
        Map<String, String> map = ReqParameter.generate()
                .add("wechatCode", wechatCode)
                .getParams();
        return wrapToSingle(baseService.wechatLogin(map));
    }

    /**
     * 用户-微信绑定和登录
     *
     * @param wechatCode 微信sdk返回的code
     * @param phone      手机号
     * @param phoneCode  短信验证码识别码
     * @return
     */
    public Single<Optional<UserMode>> wechatBind(String wechatCode, String phone, String phoneCode) {
        Map<String, String> map = ReqParameter.generate()
                .add("wechatCode", wechatCode)
                .add("mobile", phone)
                .add("verifyIdentity", phoneCode)
                .getParams();
        return wrapToSingle(baseService.wechatBind(map));
    }

    /**
     * 已登录用户-解绑微信
     *
     * @return
     */
    public Single<Optional<Object>> userWechatUnbind() {
        Map<String, String> map = ReqParameter.generate()

                .getParams();
        return wrapToSingle(baseService.userWechatUnbind(map));
    }

    /**
     * 已登录用户-绑定微信
     *
     * @param wechatCode 微信sdk返回的code
     * @return
     */
    public Single<Optional<Object>> userWechatBind(String wechatCode) {
        Map<String, String> map = ReqParameter.generate()
                .add("wechatCode", wechatCode)
                .getParams();
        return wrapToSingle(baseService.userWechatBind(map));
    }


    /**
     * 设置密码
     *
     * @param phone    手机号
     * @param passWord 新密码
     * @param code     短信验证码
     * @return
     */
    public Single<Optional<UserMode>> submitNewPwd(String phone, String passWord, String code) {
        Map<String, String> map = ReqParameter.generate()
                .add("mobile", phone).add("code", code)
                .add("newPassword", passWord)
                .getParams();
        return wrapToSingle(baseService.submitNewPwd(map));

    }

    /**
     * 修改密码
     *
     * @param newPassword 新密码
     * @param oldPassword 旧密码
     * @return
     */
    public Single<Optional<UserMode>> changePwd(String newPassword, String oldPassword) {
        Map<String, String> map = ReqParameter.generate()
                .add("newPassword", newPassword)
                .add("oldPassword", oldPassword)
                .getParams();
        return wrapToSingle(baseService.changePwd(map));

    }

    /**
     * 重置密码
     *
     * @param phone    手机号
     * @param ticket   短信验证码的识别码
     * @param password 新密码
     * @return
     */
    public Single<Optional<Object>> resetPwd(String phone, String ticket, String password) {
        Map<String, String> map = ReqParameter.generate()
                .add("mobile", phone)
                .add("verifyIdentity", ticket)
                .add("pass", password)
                .getParams();
        return wrapToSingle(baseService.resetPwd(map));

    }

    /**
     * 退出登录
     *
     * @return
     */
    public Single<Optional<String>> submitLogout() {
        return wrapToSingle(baseService.submitLogout(ReqParameter.generate().getParams()));
    }

    /**
     * 注销账户
     *
     * @return
     */
    public Single<Optional<String>> submitAccountLogout() {
        return wrapToSingle(baseService.submitAccountLogout(ReqParameter.generate().getParams()));
    }

    /**
     * 行驶证识别
     *
     * @param filePath 待识别图标
     * @return
     */
    public Single<Optional<OCRResult>> OCRDriverLicense2(final String filePath) {
        return Single.just(filePath)
                .map(new Function<String, Optional<OCRResult>>() {
                    @Override
                    public Optional<OCRResult> apply(String s) throws Exception {

                        Pair<String, String> tcOcrConfig = Configs.getTcOcrConfig();

                        TreeMap<String, String> treeMap = new TreeMap<>();
                        treeMap.put("app_id", tcOcrConfig.first);
                        treeMap.put("time_stamp", String.valueOf(System.currentTimeMillis() / 1000));
                        treeMap.put("nonce_str", UUID.randomUUID().toString().replaceAll("-", ""));
                        treeMap.put("image", Base64Util.convert(filePath, 1024 * 1024));
                        treeMap.put("type", "0");
                        treeMap.put("sign", ScUtil.ucSignForOrc(treeMap, tcOcrConfig.second));

                        Set<Entry<String, String>> entries = treeMap.entrySet();

                        FormBody.Builder formBody = new FormBody.Builder();
                        for (Entry<String, String> entry : entries) {
                            formBody.add(entry.getKey(), entry.getValue());
                        }


                        Request request = new Request.Builder().url(Configs.OCR_API)
                                .addHeader("Content-Type", "application/x-www-form-urlencoded")
                                .method("POST", formBody.build()).build();

                        OCRResult value = new OCRResult();

                        Response response = okHttpClient.newCall(request).execute();
                        if (response.isSuccessful()) {
                            String string = response.body().string();
                            if (!TextUtils.isEmpty(string)) {
                                JSONObject jsonObject = new JSONObject(string);
                                int ret = jsonObject.optInt("ret");
                                //String msg = jsonObject.optString("msg");
                                //value.msg = msg;

                                if (ret == 0) {
                                    String s1 = jsonObject.optJSONObject("data")
                                            .optJSONArray("item_list")
                                            .toString();
                                    List<OCRItem> ocrItems = JsonKit.GSON
                                            .fromJson(s1, new TypeToken<List<OCRItem>>() {
                                            }.getType());
                                    value.setOcrItems(ocrItems);
                                }

                                StatTools.sendShow(AppContext.getContext(), StatisticsId.ocr_tc_result, "" + ret);

                            } else {
                                StatTools.sendShow(AppContext.getContext(), StatisticsId.ocr_tc_result, "json_error");
                            }

                        } else {
                            StatTools.sendShow(AppContext.getContext(), StatisticsId.ocr_tc_result, "resp_error");
                        }
                        return Optional.of(value);
                    }
                })
                .compose(RxHelper.<Optional<OCRResult>>io2main());

    }


    /**
     * 更新用户头像
     *
     * @param path oss路径
     * @return
     */
    public Single<Optional<UserMode>> submitUserInfoHeader(String path) {
        final Map<String, String> map = ReqParameter.generate()
                .add("headImg", path).getParams();
        return wrapToSingle(baseService.submitUserInfoHeader(map));
    }

    /**
     * 更新用户昵称
     *
     * @param nickName
     * @return
     */
    public Single<Optional<UserMode>> submitUpdateNickName(String nickName) {
        Map<String, String> map = ReqParameter.generate().add("nickname", nickName).getParams();
        return wrapToSingle(baseService.fetchUpdateNickName(map));
    }

    /**
     * 获取用户信息
     *
     * @return
     */
    public Single<Optional<UserMode>> getUserInfo() {
        Map<String, String> map = ReqParameter.generate()
                .getParams();
        return wrapToSingle(baseService.getUserInfo(map));
    }


    @Deprecated
    public Single<Optional<UpgradeModel>> checkVersionInfo() {
//        final Map<String, String> map = ReqParameter.generate()
//                .add("versionCode", BuildConfig.VERSION_CODE)
//                .add("channel", BuildConfig.UPDATE_CHANNEL).getParams();
//        return wrapToSingle(baseService.fetchVersion(map));
        return wrapToSingle(baseService.checkUpgrade(ReqParameter.generate().getParams()));
    }

    /**
     * 获取账本列表
     *
     * @return
     */
    public Single<Optional<BookMode>> fetchBillList() {
        Map<String, String> map = ReqParameter.generate().getParams();
        return wrapToSingle(baseService.fetchBillList(map));
//            .map(new BookListTransform())
//            .compose(RxHelper.<Optional<BookMode>>io2main());

    }

    public Single<Optional<Object>> submitBill(String text, String content, String remarks, String dateStr, int id) {
        ReqParameter parameter = ReqParameter.generate().add("amount", text).add("tagName", content)
                .add("remarks", remarks)
                .add("expensesDate", dateStr);
        if (id == -1) {
            return wrapToSingle(baseService.submitBill(parameter.getParams()));
        } else {
            parameter.add("id", id);
            return wrapToSingle(baseService.submitUpdateBill(parameter.getParams()));
        }

    }


    public Single<Optional<Object>> submitDel(int id) {
        return wrapToSingle(baseService.submitDel(ReqParameter.generate("id", String.valueOf(id)).getParams()));
    }


    /**
     * 获取最新消息
     *
     * @return
     */
    public Single<Optional<MessageMode>> fetchPushMessage() {
        Map<String, String> map = ReqParameter.generate().getParams();
        return wrapToSingle(baseService.fetchPushMessage(map));
    }


    /**
     * 获取消息列表
     *
     * @param type   消息类型
     * @param typeId 类型id
     * @param page   页数
     * @return
     */
    public Single<Optional<PageList<MessageDetail>>> getMessageList(String type, int typeId, int page) {
        Map<String, String> map = ReqParameter.generate()
                .add("type", type)
                .add("typeId", typeId)
                .add("page", page)
                .getParams();
        return wrapToSingle(baseService.getMessageList(map));

    }


    /**
     * 设置消息已读
     *
     * @param flag
     * @param typeId
     * @return
     */
    public Single<Optional<Object>> submitReady(String flag, int typeId) {
        return wrapToSingle(baseService.submitReady(ReqParameter.generate("type", flag).add("typeId", typeId).getParams()));
    }


    /**
     * 获取推送标签
     *
     * @param lon  经纬度
     * @param lat
     * @param city 城市code
     * @return
     */
    public Single<Optional<Map<String, String>>> getPushTags(double lon, double lat, String city) {
        ReqParameter params = ReqParameter.generate()
                .add("versionCode", String.valueOf(BuildConfig.VERSION_CODE))
                .add("channel", ChannelManager.getChannel());

        if (lon > 0) {
            params.add("lon", String.valueOf(lon));
        }
        if (lat > 0) {
            params.add("lat", String.valueOf(lat));
        }

        if (!TextUtils.isEmpty(city)) {
            params.add("cityName", city);
        }

        return wrapToSingle(baseService.getPushTags(params.getParams()));
    }


    /**
     * 获取养车小技巧提示
     *
     * @return
     */
    public Single<Optional<Map<String, List<CarTips>>>> getCarTips() {
        Map<String, String> params = ReqParameter.generate()
                .getParams();

        if (BuildConfig.DEBUG) {
            return wrapToSingle(baseService.getCarTips(params));
        } else {
            return wrapToSingle(baseService.getCarTips(params), "car-tips-help", new TypeToken<Map<String, List<CarTips>>>() {
            }.getType(), TimeUnit.MINUTES.toSeconds(30));
        }
//      return wrapToSingle(baseService.getCarTips(params),"car-tips-help",new TypeToken<Map<String,List<CarTips>>>(){}.getType(),TimeUnit.DAYS.toSeconds(3));

    }

    public Single<Optional<CheckLicenseAvailableModel>> checkLicenseAvailable(String province, String alphabet) {
        Map<String, String> params = ReqParameter.generate()
                .add("provinceAbbr", province)
                .add("licenseInitial", alphabet).getParams();
        return wrapToSingle(baseService.checkLicenseAvailable(params));
    }

    public Single<Optional<CheckLicenseAvailableModel>> checkLicenseByLocation(String province, String city) {
        Map<String, String> params = ReqParameter.generate()
                .add("province", province)
                .add("cityName", city).getParams();
        return wrapToSingle(baseService.checkLicenseByLocation(params));
    }

    /**
     * 违章查询，新增车辆并查询
     *
     * @param map
     * @return
     */
    public Single<Optional<TrafficViolationResp>> violationQuery(Map<String, String> map) {

        if (Tools.getSp().getBoolean(DataCenter.KEY_SUBSCRIBE_NOTIFY, false)) {
            map.put("violationSubscribe", "1");
        } else {
            map.put("violationSubscribe", "0");
        }
        ReqParameter reqParameter = ReqParameter.generate().addAll(map);

        return wrapToSingle(baseService.violationQuery(reqParameter.getParams()));
    }

    /**
     * 根据车辆id查询违章列表
     *
     * @param carId 车辆id
     * @return
     */
    public Single<Optional<TrafficViolationResp>> carFineList(int carId) {
        return wrapToSingle(baseService.carFineList(ReqParameter.generate("userCarId", String.valueOf(carId)).getParams()));
    }

    /**
     * 我的车辆列表
     *
     * @return
     */
    public Single<Optional<List<UserCarInfo>>> myCars() {
        return wrapToSingle(baseService.myCars(ReqParameter.generate().getParams())).map(new ListMapFunction<UserCarInfo>());
    }

    /**
     * 更新车辆信息
     *
     * @param map
     * @return
     */
    public Single<Optional<UserCarInfo>> updateCar(Map<String, String> map) {
        if (Tools.getSp().getBoolean(DataCenter.KEY_SUBSCRIBE_NOTIFY, false)) {
            map.put("violationSubscribe", "1");
        } else {
            map.put("violationSubscribe", "0");
        }
        return wrapToSingle(baseService.updateCar(ReqParameter.generate().addAll(map).getParams()));
    }

    /**
     * 删除车辆
     *
     * @param carId 车辆id
     * @return
     */
    public Single<Optional<Object>> deleteCar(int carId) {
        return wrapToSingle(baseService.deleteCar(ReqParameter.generate("userCarId", String.valueOf(carId)).getParams()));
    }

    /**
     * 上传识别的ocr信息
     *
     * @param text
     * @return
     */
    public Single<Optional<String>> reportOcrResult(String text) {
        return wrapToSingle(baseService.reportOcrResult(ReqParameter.generate("ocrStr", text).getParams()));
    }

    /**
     * 获取车管所服务类型
     *
     * @return
     */
    public Single<Optional<List<ServiceCatagory>>> getServiceCatagories() {

        return wrapToSingle(baseService.getServiceCatagories(ReqParameter.generate().getParams()),
                "get-gov-services-type",
                new TypeToken<ListResult.ListData<ServiceCatagory>>() {
                }.getType(),
                TimeUnit.DAYS.toSeconds(7))
                .map(new ListMapFunction<ServiceCatagory>());
    }


    /**
     * 获取车管所列表
     *
     * @param page
     * @param cityId
     * @param serviceCodes
     * @param lat
     * @param lon
     * @return
     */
    public Single<Optional<PageList<DepartmentInfo>>> getDepartmentInfo(int page, int cityId, String serviceCodes, double lat, double lon) {
        Map<String, String> params = ReqParameter.generate()
                .add("page", String.valueOf(page))
                .add("cityId", String.valueOf(cityId))
                .add("lat", String.valueOf(lat))
                .add("lon", String.valueOf(lon))
                .add("serviceCodes", TextUtils.isEmpty(serviceCodes) ? "" : serviceCodes).getParams();
        return wrapToSingle(baseService.getDepartmentInfo(params));
    }


    public Single<Optional<TabConfResp>> getTabConfigs() {
        ReqParameter generate = ReqParameter.generate();
        WZCity currentWZCity = LocManager.getInstance().getCurrentWZCity();
        String areaCode = "0";
        if (currentWZCity != null && !TextUtils.isEmpty(currentWZCity.areaCode)) {
            areaCode = currentWZCity.areaCode;
            generate.add("areaCode", currentWZCity.areaCode);
        }
        Map<String, String> params = generate.getParams();

        if (BuildConfig.DEBUG) {
            return wrapToSingle(baseService.getTabConf(params));
        } else {
            return wrapToSingle(baseService.getTabConf(params), "home-all-tab-conf_" + areaCode, new TypeToken<TabConfResp>() {
            }.getType(), TimeUnit.MINUTES.toSeconds(5));

        }

//    return wrapToSingle(baseService.getGarageConf(params),"home-tab-conf",new TypeToken<TabConfResp>(){}.getType(),TimeUnit.DAYS.toSeconds(1));

    }


    /**
     * 提交罚款代缴订单
     *
     * @param _id         罚单编号
     * @param contactName 被处罚人
     * @param tel         电话
     * @param money       罚款金额
     * @param serviceFee  服务费
     * @param date        处罚时间
     * @param payType     支付方式
     * @param img         罚单照片
     * @param quickStatus 是否极速办理
     * @param cheCarData  是否能通过接口查询到罚单信息
     * @param couponId    优惠券id
     * @return
     */
    public Single<Optional<PaymentOrder>> submitFKDJMode(@NonNull String _id, @NonNull String contactName, @NonNull String tel, @Nullable String money,
                                                         @Nullable String serviceFee,
                                                         @Nullable String date,
                                                         @Nullable String payType,
                                                         @Nullable String img, boolean quickStatus, boolean cheCarData, long couponId) {

        Map<String, String> map = new HashMap<>();
        map.put("pinZhenHao", _id);
        map.put("contactName", contactName);
        map.put("tel", tel);
        map.put("money", money);
        map.put("serviceFee", serviceFee);
        map.put("date", date);
        map.put("payType", payType);
        if (img != null) {
            map.put("uploadImage", img);
        }

        map.put("quickStatus", quickStatus ? "1" : "0");
        map.put("cheCarData", cheCarData ? "1" : "0");
        if (couponId > 0) {
            map.put("couponId", String.valueOf(couponId));
        }

        return wrapToSingle(baseService.submitFKDJMode(ReqParameter.generate().addAll(map).getParams()));

    }


    /**
     * 获取违章代办列表
     *
     * @param mode
     * @return
     */
    public Single<Optional<List<WZDBMode>>> fetchWZDBData(UserCarInfo mode) {
        Map<String, String> map = ReqParameter.generate()
                .add("carNo", mode.carNo)
                .add("carType", mode.carType)
                .add("engineNo", mode.engineNo)
                .add("frameNo", mode.frameNo)
                .getParams();
        return wrapToSingle(baseService.fetchWZDBData(map));
    }

    /**
     * 提交违章代办
     *
     * @param lists 违章代办列表违章id,多个用,分隔
     * @return
     */
    public Single<Optional<WzdbCreateResp>> submitWZDBList(String lists) {
        Map<String, String> map = ReqParameter.generate()
                .add("uniqueMd5Id", lists)
                .getParams();
        return wrapToSingle(baseService.submitWZDBList(map));

    }

    private List<MultipartBody.Part> convert2Multipart(Map<String, Object> data) {
        ReqParameter parameter = ReqParameter.generate();
        List<MultipartBody.Part> parts = new ArrayList<>();
        for (Map.Entry<String, Object> entry : data.entrySet()) {
            String key = entry.getKey();
            Object value = entry.getValue();
            if (value instanceof String) {
                parameter.add(key, value.toString());
            } else if (value instanceof File && ((File) value).exists()) {
                //单个文件
                parts.add(MultipartBody.Part.createFormData(key, ((File) value).getName(),
                        RequestBody.create(MediaType.parse("image/jpg"), (File) value)));
            } else if (value instanceof List && !((List) value).isEmpty() && ((List) value).get(0) instanceof File) {
                //文件列表
                List<File> files = (List<File>) value;
                for (File file : files) {
                    if (file != null) {
                        parts.add(MultipartBody.Part.createFormData(key, file.getName(),
                                RequestBody.create(MediaType.parse("image/jpg"), file)));
                    }

                }
            }
        }
        for (Map.Entry<String, String> entry : parameter.getSingedParams().entrySet()) {
            parts.add(MultipartBody.Part.createFormData(entry.getKey(), entry.getValue()));
        }

        return parts;
    }

    /**
     * 上传违章代办补充信息
     *
     * @param lists
     * @param data
     * @return
     */
    public Single<Optional<WzdbOrderInfo>> addWZDBCertInfo(String lists, Map<String, Object> data) {
        data.put("uniqueMd5Id", lists);

        return wrapToSingle(baseService.addWZDBCertInfo(convert2Multipart(data)));

    }

    /**
     * 违章代办支付
     *
     * @param orderNo  订单号
     * @param payStyle 支付方式
     * @param phone    联系电话
     * @param name     联系人姓名
     * @return
     */
    public Single<Optional<PaymentOrder>> payWZDB(String orderNo, String payStyle, String phone, String name) {
        Map<String, String> map = ReqParameter.generate()
                .add("orderNo", orderNo)
                .add("payType", payStyle)
                .add("tel", phone)
                .add("contactName", name)
                .getParams();
        return wrapToSingle(baseService.payWZDB(map));

    }

    /**
     * 获取违章代办订单信息
     *
     * @param orderNo
     * @return
     */
    public Single<Optional<WzdbOrderInfo>> getWZDBOrderInfo(String orderNo) {
        Map<String, String> map = ReqParameter.generate()
                .add("orderNo", orderNo)
                .getParams();
        return wrapToSingle(baseService.getWZDBOrderInfo(map));

    }


    /**
     * 罚单编号识别
     *
     * @param fineNumber
     * @return
     */
    public Single<Optional<FinePaymentDetail>> checkFineNo(String fineNumber) {
        Map<String, String> map = ReqParameter.generate()
                .add("fineNumber", fineNumber)
                .getParams();
        return wrapToSingle(baseService.checkFineNo(map));

    }

    /**
     * 违章代办补充资料
     *
     * @param orderNo
     * @return
     */
    public Single<Optional<WzdbCreateResp>> fetchOrderNeedParams(String orderNo) {
        Map<String, String> map = ReqParameter.generate()
                .add("orderNo", orderNo).getParams();
        return wrapToSingle(baseService.fetchOrderNeedParams(map));
    }

    /**
     * 提交违章代办补充资料
     *
     * @param orderNo
     * @param map
     * @return 根据code判断  不要传数据
     */
    public Single<Optional<WzdbOrderInfo>> submitNeedParams(String orderNo, Map<String, Object> map) {

        map.put("orderNo", orderNo);

//        ReqParameter params = ReqParameter.generate().add("orderNo", orderNo);
//        for (Map.Entry<String, Object> entry : map.entrySet()) {
//            String key = entry.getKey();
//            Object value = entry.getValue();
//            if (value instanceof String) {
//                params.add(key, value.toString());
//            } else if (value instanceof File && ((File) value).exists()) {
//                parts.add(MultipartBody.Part.createFormData(key, ((File) value).getName(), RequestBody.create(MediaType.parse("image/jpg"), (File) value)));
//            }
//        }
//        for (Map.Entry<String, String> entry : params.getSingedParams().entrySet()) {
//            parts.add(MultipartBody.Part.createFormData(entry.getKey(), entry.getValue()));
//        }


        return wrapToSingle(baseService.submitNeedParams(convert2Multipart(map)));
    }

    public Single<Optional<List<MyOrderMode>>> fetchOrderList() {
        Map<String, String> map = ReqParameter.generate().getParams();
        return wrapToSingle(baseService.fetchOrderList(map));
    }


    /**
     * 获取新闻分类
     *
     * @return
     */
    public Single<Optional<List<NewsCategory>>> getNewsCategories() {
        return wrapToSingle(baseService.getNewsCategories(ReqParameter.generate().getParams()))
                .map(new ListMapFunction<NewsCategory>());
    }

    /**
     * 获取新闻分类
     *
     * @return
     */
    public Single<Optional<List<NewsCategory>>> getNewsCategories(String type) {
        return wrapToSingle(baseService.getNewsCategories(ReqParameter.generate()
                .add("position", type)
                .getParams()))
                .map(new ListMapFunction<NewsCategory>());
    }

    /**
     * 获取新闻列表
     *
     * @param page 分页1
     * @param type 类型
     * @return
     */
    public Single<Optional<PageList<NewsModel>>> getNews(int page, String type) {
        Map<String, String> map = ReqParameter.generate()
                .add("page", String.valueOf(page))
                .add("pinyinAbbr", type)
                .getParams();

        return wrapToSingle(baseService.getNews(map));
    }

    /**
     * 获取推荐新闻列表
     *
     * @return
     */
    public Single<Optional<List<NewsModel>>> getRecommendNews() {
        Map<String, String> map = ReqParameter.generate()
                .getParams();

        return wrapToSingle(baseService.getRecommendNews(map));
    }


    /**
     * 获取品牌
     *
     * @return
     */
    public Single<Optional<List<CarTypeResp>>> carBrands() {
        return wrapToSingle(baseService.carBrands(ReqParameter.generate().getParams()),
                "api_car_brands",
                new TypeToken<List<CarTypeResp>>() {
                }.getType(),
                TimeUnit.DAYS.toSeconds(3));
    }

    /**
     * 获取车系
     *
     * @param brandId 品牌id
     * @return
     */
    public Single<Optional<List<CarTypeResp>>> carSeries(String brandId) {
        Map<String, String> map = ReqParameter.generate()
                .add("brandId", brandId)
                .getParams();
        return wrapToSingle(baseService.carSeries(map), "api_car_series_" + brandId,
                new TypeToken<List<CarTypeResp>>() {
                }.getType(),
                TimeUnit.DAYS.toSeconds(3));
    }


    /**
     * 获取车型
     *
     * @param seriesId 车系id
     * @return
     */
    public Single<Optional<List<CarTypeResp>>> carSpecification(String seriesId) {
        Map<String, String> map = ReqParameter.generate()
                .add("seriesId", seriesId)
                .getParams();
        return wrapToSingle(baseService.carSpecification(map), "api_car_specification_" + seriesId,
                new TypeToken<List<CarTypeResp>>() {
                }.getType(),
                TimeUnit.DAYS.toSeconds(3));
    }


    /**
     * 保险公司列表
     *
     * @return
     */
    public Single<Optional<List<String>>> carInsuranceCompany() {
        return wrapToSingle(baseService.carInsuranceCompany(ReqParameter.generate().getParams()), "api_car_insurance_company",
                new TypeToken<List<String>>() {
                }.getType(),
                TimeUnit.DAYS.toSeconds(3));
    }

    /**
     * 添加车辆保险信息
     *
     * @param userCarId 车辆id
     * @param date      日期
     * @param company   保险公司
     * @return
     */
    public Single<Optional<CarExtendInfo>> carInsurance(int userCarId, String date, String company) {
        Map<String, String> map = ReqParameter.generate()
                .add(USER_CAR_ID, userCarId)
                .add("insuranceDate", date)
                .add("insuranceCompany", company)
                .getParams();
        return wrapToSingle(baseService.carInsurance(map));
    }


    /**
     * 添加年检信息更新的
     *
     * @param userCarId
     * @param regDate      上牌时间
     * @param validityDate 检验有效期
     * @return
     */
    public Single<Optional<CarExtendInfo>> carInspection(int userCarId, String regDate,
                                                         String validityDate,
                                                         String mannedNum,
                                                         String carType,
                                                         String natureOfUse,
                                                         String inspectReminder) {
        Map<String, String> map = ReqParameter.generate()
                .add(USER_CAR_ID, userCarId)
                .add("registerLicenseDate", regDate)
                .add("licenseValidityDate", validityDate)
                .add("mannedNum", mannedNum)  //车辆类型
                .add("carType", carType) //车辆类型
                .add("natureOfUse", natureOfUse) //使用性质
                .add("inspectReminder", inspectReminder) //年检提醒
                .getParams();
        return wrapToSingle(baseService.carInspection(map));
    }




//    /**
//     * 添加年检信息
//     *
//     * @param userCarId
//     * @param regDate      上牌时间
//     * @param validityDate 检验有效期
//     * @return
//     */
//    public Single<Optional<CarExtendInfo>> carInspection(int userCarId, String regDate, String validityDate) {
//        Map<String, String> map = ReqParameter.generate()
//                .add(USER_CAR_ID, userCarId)
//                .add("registerLicenseDate", regDate)
//                .add("licenseValidityDate", validityDate)
//                .getParams();
//        return wrapToSingle(baseService.carInspection(map));
//    }



    /**
     * 添加车辆估值
     *
     * @param userCarId
     * @param specificationId       车型id
     * @param registerLicenseDate   上牌时间
     * @param drivenDistance        公里数
     * @param registerLicenseCityId 城市
     * @return
     */
    public Single<Optional<CarExtendInfo>> carValuation(int userCarId, String specificationId, String registerLicenseDate, String drivenDistance, String registerLicenseCityId) {
        Map<String, String> map = ReqParameter.generate()
                .add(USER_CAR_ID, userCarId)
                .add("specificationId", specificationId)
                .add("registerLicenseDate", registerLicenseDate)
                .add("drivenDistance", drivenDistance)
                .add("registerLicenseCityId", registerLicenseCityId)
                .getParams();
        return wrapToSingle(baseService.carValuation(map));
    }


    /**
     * 精真估城市列表
     *
     * @return
     */
    public Single<Optional<Map<String, List<JZGCity>>>> carTypeJZGCity() {
        Map<String, String> map = ReqParameter.generate()
                .getParams();

//    return wrapToSingle(baseService.carTypeCity(map));
        return wrapToSingle(baseService.carTypeCity(map), "api_car_type_city_jzg",
                new TypeToken<Map<String, List<JZGCity>>>() {
                }.getType(),
                TimeUnit.DAYS.toSeconds(15));
    }


    /**
     * 提交估值线索
     *
     * @param userCarId
     * @return
     */
    public Single<Optional<Object>> jzgClues(int userCarId) {
        Map<String, String> map = ReqParameter.generate()
                .add("userCarId", userCarId)
                .getParams();

        return wrapToSingle(baseService.jzgClues(map));
    }


    /**
     * 城市列表
     *
     * @return
     */
    public Single<Optional<CityListResp>> cityList() {
        Map<String, String> map = ReqParameter.generate()
                .getParams();

        return wrapToSingle(baseService.cityList(map), "api_car_type_city",
                new TypeToken<CityListResp>() {
                }.getType(),
                TimeUnit.DAYS.toSeconds(7));
//    return wrapToSingle(baseService.cityList(map));
    }

    /**
     * 获取系统配置
     *
     * @return
     */
    public Single<Optional<SysConfMap>> getSysConf() {
        Map<String, String> map = ReqParameter.generate()
                .getParams();
//    return wrapToSingle(baseService.getSysConf(map),"api_sys_conf",
//        new TypeToken<SysConfMap>(){}.getType(),
//        TimeUnit.HOURS.toSeconds(8));
        return wrapToSingle(baseService.getSysConf(map));
    }


    /**
     * 年检有效期
     *
     * @param regTime
     * @return
     */
    public Single<Optional<String>> inspectionEndTime(String regTime) {
        Map<String, String> map = ReqParameter.generate()
                .add("registerLicenseDate", regTime)
                .getParams();
        return wrapToSingle(baseService.inspectionEndTime(map));
    }


    public Single<Optional<List<TopicTagType>>> getTopicTags() {
        Map<String, String> map = ReqParameter.generate()
                .getParams();
        if (BuildConfig.DEBUG) {
            return wrapToSingle(baseService.getTopicTags(map));
        } else {
            return wrapToSingle(baseService.getTopicTags(map), "app-topic-tags", new TypeToken<List<TopicTagType>>() {
            }.getType(), TimeUnit.MINUTES.toSeconds(30));
        }

    }

    public Single<Optional<TopicListResp>> topicList(long upperId, long underId) {
        ReqParameter parameter = ReqParameter.generate();
        if (upperId > 0) {
            parameter.add("upperId", upperId);
        }
        if (underId > 0) {
            parameter.add("underId", underId);
        }

        return wrapToSingle(baseService.topicList(parameter.getParams()));
    }

    public Single<Optional<TopicModel>> createTopic(String content, String topicTagId, List<File> files) {

        Map<String, Object> map = new HashMap<>();
        map.put("content", content);
        if (topicTagId != null) {
            map.put("topicId", topicTagId);
        }
        if (files != null && !files.isEmpty()) {
            map.put("images[]", files);
        }


        return wrapToSingle(baseService.createTopic(convert2Multipart(map)));
    }


    public Single<Optional<Object>> topicAddLike(long topicId) {
        Map<String, String> map = ReqParameter.generate()
                .add("bbsId", topicId)
                .getParams();
        return wrapToSingle(baseService.topicAddLike(map));
    }

    public Single<Optional<PageList<CommentModel>>> getCommentList(int page, long topicId) {
        Map<String, String> map = ReqParameter.generate()
                .add("page", String.valueOf(page))
                .add("bbsId", topicId)
                .getParams();

        return wrapToSingle(baseService.getCommentList(map));
    }


    public Single<Optional<Object>> commentAddLike(long commentId) {
        Map<String, String> map = ReqParameter.generate()
                .add("commentId", commentId)
                .getParams();
        return wrapToSingle(baseService.commentAddLike(map));
    }

    public Single<Optional<CommentModel>> addComment(long topicId, String content) {
        Map<String, String> map = ReqParameter.generate()
                .add("bbsId", topicId)
                .add("content", content)
                .getParams();
        return wrapToSingle(baseService.addComment(map));
    }

    public Single<Optional<Object>> topicDelete(long topicId) {
        Map<String, String> map = ReqParameter.generate()
                .add("bbsId", topicId)
                .getParams();
        return wrapToSingle(baseService.topicDelete(map));
    }

    public Single<Optional<TopicViewResp>> topicView(long topicId) {
        Map<String, String> map = ReqParameter.generate()
                .add("bbsId", topicId)
                .getParams();
        return wrapToSingle(baseService.topicView(map));
    }

    /**
     * 获取所有广告
     *
     * @return
     */
    public Single<Optional<AdConfigs>> getAllAdConfig() {
        Map<String, String> map = ReqParameter.generate()
                .getParams();

        if (BuildConfig.DEBUG) {
            return wrapToSingle(baseService.getAllAdConfig(map));
        } else {
            return wrapToSingle(baseService.getAllAdConfig(map), "app-all-ads-conf", new TypeToken<AdConfigs>() {
            }.getType(), TimeUnit.MINUTES.toSeconds(5));
        }

    }


    public Single<Optional<Map<String, String>>> getAllAdIdConfig() {
        Map<String, String> map = ReqParameter.generate()
                .getParams(false);
        return wrapToSingle(baseService.getAllAdIdConfig(map));
    }

    public Single<Optional<CouponResp>> couponList() {
        Map<String, String> map = ReqParameter.generate()
                .getParams();
        return wrapToSingle(baseService.couponList(map));
    }

    /**
     * 今日油价
     *
     * @param provinceId 省份id
     * @return
     */
    public Single<Optional<OilPriceResp>> oilPriceList(int provinceId) {
        Map<String, String> map = ReqParameter.generate()
                .add("area_id", provinceId)
                .getParams();
        return wrapToSingle(baseService.oilPriceList(map));
    }


    /**
     * 获取阿里云oss上传token
     *
     * @param type
     * @return
     */
    public Single<Optional<OSSToken>> getOSSToken(String type) {
        Map<String, String> map = ReqParameter.generate()
                .add("type", type)
                .getParams();
        return wrapToSingle(baseService.getOSSToken(map));
    }


    /**
     * 上传文件
     *
     * @param type
     * @param files
     * @return
     */
    public Single<Map<String, OSSUploadResult>> uploadFiles(String type, final Map<String, File> files) {
        return getOSSToken(type).compose(RxHelper.<Optional<OSSToken>>switch2io())
                .flatMap(
                        new Function<Optional<OSSToken>, SingleSource<Map<String, OSSUploadResult>>>() {
                            @Override
                            public SingleSource<Map<String, OSSUploadResult>> apply(
                                    final Optional<OSSToken> ossTokenOptional) throws Exception {

                                return Single.fromCallable(new Callable<Map<String, OSSUploadResult>>() {
                                    @Override
                                    public Map<String, OSSUploadResult> call() throws Exception {
                                        return FileUtils.uploadToOSS(ossTokenOptional.orNull(), files);
                                    }
                                });
                            }
                        }).compose(RxHelper.<Map<String, OSSUploadResult>>io2main());
    }


    /**
     * 提交反馈
     *
     * @param type    反馈类型
     * @param content 反馈内容
     * @param images  上传图片
     * @return
     */
    public Single<Optional<Object>> submitFeedback(int type, String content, String images) {
        Map<String, String> map = ReqParameter.generate()
                .add("type", type)
                .add("content", content)
                .add("images", images)
                .getParams();
        return wrapToSingle(baseService.submitFeedback(map));
    }

    /**
     * 我的反馈列表
     *
     * @return
     */
    public Single<Optional<List<FeedbackModel>>> myFeedbackList() {
        Map<String, String> map = ReqParameter.generate()
                .getParams();
        return wrapToSingle(baseService.myFeedbackList(map));
    }

    /**
     * 常见问题
     *
     * @return
     */
    public Single<Optional<List<CommonFeedbackQA>>> commonFeedbackList() {
        Map<String, String> map = ReqParameter.generate()
                .getParams();
        return wrapToSingle(baseService.commonFeedbackList(map));
    }

    /**
     * 122查询
     *
     * @param params
     * @return
     */
    public Single<Optional<GovParseResp>> govQueryParse(Map<String, String> params) {
        Map<String, String> map = ReqParameter.generate()
                .addAll(params)
                .getParams();

        return wrapToSingle(baseService.govQueryParse(map));
    }


    /**
     * 获取历史违章
     *
     * @param carNo
     * @return
     */
    public Single<Optional<List<TrafficViolationInfo>>> getFineHistory(String carNo) {
        Map<String, String> map = ReqParameter.generate()
                .add("carNo", carNo)
                .getParams();
        return wrapToSingle(baseService.getFineHistory(map));
    }


    /**
     * 识别验证码
     *
     * @param base64Image 图片验证码
     * @param type        类型
     * @return
     */
    public Single<Optional<String>> decodeCaptchaImage(String base64Image, String type) {
        Map<String, String> map = ReqParameter.generate()
                .add("imageBase64", base64Image)
                .add("type", type)
                .getParams();
        return wrapToSingle(baseService.decodeCaptchaImage(map));
    }


    public Single<Optional<List<BgWorkModel>>> getBgWorkList() {
        return wrapToSingle(baseService.getBgWorkList(ReqParameter.generate().getParams()));
    }


    /**
     * 创建年检代办接口
     *
     * @return
     */
    public Single<Optional<PaymentOrder>> createInspection(Map<String, String> params) {
        Map<String, String> map = ReqParameter.generate()
                .addAll(params)
                .getParams();
        return wrapToSingle(baseService.createInspection(map));
    }


    /**
     * 获取年检代办配置
     *
     * @return
     */
    public Single<Optional<NjdbPreModel>> getInspectionModel(int userCarId) {
        Map<String, String> map = ReqParameter.generate()
                .add(USER_CAR_ID, userCarId)
                .getParams();
        return wrapToSingle(baseService.getInspectionModel(map));
    }


    /**
     * 获取年检代办配置
     *
     * @return
     */
    public Single<Optional<OCRResult>> ocrDrivingLicence(File file) {
        Map<String, Object> map = new HashMap<>(1);
        map.put("image", file);
        return wrapToSingle(baseService.ocrDrivingLicence(convert2Multipart(map)));
    }


    /**
     * 检查更新
     *
     * @return
     */
    public Single<Optional<UpgradeModel>> checkUpgrade() {
        return wrapToSingle(baseService.checkUpgrade(ReqParameter.generate().getParams()));
    }


    /**
     * 检测支付状态
     *
     * @param orderNo 订单号
     * @param payType 支付类型
     * @return
     */
    public Single<Optional<OrderStatus>> checkPayStatus(String orderNo, int payType) {
        return wrapToSingle(baseService.checkPayStatus(ReqParameter.generate()
                .add("orderNo", orderNo)
                .add("payType", payType)
                .getParams()));
    }


    /**
     * 获取验证码
     *
     * @return
     */
    public Single<Optional<CaptchaData>> getCaptcha() {
        return wrapToSingle(baseService.getCaptcha(ReqParameter.generate()
                .getParams()));
    }

    /**
     * 验证验证码
     *
     * @return
     */
    public Single<Optional<CaptchaValidData>> validCaptcha(ValidReq validReq) {
        ReqParameter parameter = ReqParameter.generate();


        if (TextUtils.equals(validReq.getType(), IValidator.TC)) {
            parameter.add("ticket", validReq.getTicket())
                    .add("aid", validReq.getAid())
                    .add("randstr", validReq.getRandStr());

            return wrapToSingle(baseService.validCaptchaTc(parameter.getParams()));

        } else if (TextUtils.equals(validReq.getType(), IValidator.IMG)) {
            parameter.add("unique", validReq.getUniqueCode())
                    .add("code", validReq.getCode());

            return wrapToSingle(baseService.validCaptcha(parameter.getParams()));
        }

        return null;

    }

    /**
     * 订阅通知
     *
     * @return
     */
    public Single<Optional<Object>> subscribeNotify(String type, boolean status) {
        return wrapToSingle(baseService.subscribeNotify(ReqParameter.generate()
                .add("type", type)
                .add("status", status ? 1 : 0)
                .getParams()));
    }
}
